local cjson = require "cjson"
local mysql = require "resty.mysql"

local resp = {
    message = nil,
    success = false
}

local db = mysql:new()
local ok, err, errcode, sqlstate = db:connect({
    host = "127.0.0.1",
    port = 3306,
    database = "dataway",
    user = "root",
    password = "Lzslov123!"})

if not ok then
    resp.message = string.format([[bad result #1: %s]], err)
    ngx.say(cjson.encode(resp))
    ngx.exit(200)
end

local function error_handle()
    -- ngx.say(cjson.encode(resp))
    ngx.say(debug.traceback("Traceback"))
end

local function find_location(uri)
    local s, err = ngx.shared.DICT:get("my_locs")
    if not s then 
        resp.message = "have no location, try reload"
        ngx.say(cjson.encode(resp))
        ngx.exit(200)
    end

    local data = cjson.decode(s)
    local locations = require("resty.locations")
    local my_locs = locations:new()
    for _, v in pairs(data) do 
        if v.modifier==ngx.null then 
            my_locs:set(v.location, v.id)
        else
            my_locs:set(v.location, v.id, v.modifier)
        end
    end

    local val, err = my_locs:lookup(ngx.var.uri)
    if val then
        return val 
    else
        if err then
            resp.message = err
        else
            resp.message = "match no locations!"
        end

        ngx.say(cjson.encode(resp))
        ngx.exit(200)
    end
end

local function _do_sql(r)
    local ok, err = xpcall(
        function(r, db, resp) 
            local ok, err, errcode, sqlstate = db:connect({
                host = r.host,
                port = r.port,
                database = r.database,
                user = r.user,
                password = r.passwd})
        
            if not ok then
                resp.message = string.format([[failed to connect: %s]], err)
                ngx.say(cjson.encode(resp))
                ngx.exit(200)
            end
        
            local f = loadstring(r.script)
            local sql = f()
            res, err = db:query(sql)
            if not res then
                resp.message = string.format([[bad result #1: %s]], err)
            else
                resp.success = true
                resp.data = res
                local ok, err = db:set_keepalive(10000, 50)
                if not ok then
                    ngx.log(ngx.ERR, "failed to set keepalive: ", err)
                end
            end

            ngx.say(cjson.encode(resp))
        end, error_handle, r, db, resp)
end

local function _do_script(r)
    local f, err
    if r.simple==2 then 
        f, err = loadstring(r.script)
    elseif r.simple==3 then 
        f, err = loadfile(r.script)
    end 

    if not f then 
        resp.message = err
        ngx.say(cjson.encode(resp))
        ngx.exit(200)
    end

    local ok, err = xpcall(f, error_handle)
end

local id = find_location(ngx.var.uri)
local sql = string.format([[
    select script, simple,host,port,user,passwd,d.database
    from datasource_tab d inner join location_tab l
    on(d.id=l.datasource_id)
    where l.id = %d
    ]], id)

res, err, errcode, sqlstate = db:query(sql)
if not res then
    resp.message = string.format([[bad result #1: %s]], err)
    ngx.say(cjson.encode(resp))
    ngx.exit(200)
end
if not next(res) then 
    resp.message = "have not found match id:"..id .." in location_tab"
    ngx.say(cjson.encode(resp))
    ngx.exit(200)
end 
local r = res[1]
if not r.script then 
    resp.message = err
    ngx.say(cjson.encode(resp))
    ngx.exit(200)
end 

if r.simple==1 then 
    _do_sql(r)
else
    _do_script(r)
end

